home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / VideoToolbox 96.06.15 / VideoToolboxSources / SetGestaltValue1.c < prev    next >
Text File  |  1996-05-09  |  8KB  |  210 lines

  1. /*
  2. SetGestaltValue1.c
  3.  
  4. enum{gestaltPsychTable='Psyc'}                        // this can be whatever you want
  5.  
  6. error=SetGestaltValue1(gestaltPsychTable,table);    // install a table address
  7. error=SetGestaltValue1(gestaltPsychTable,NULL);        // replace the table address with NULL
  8.  
  9. error=Gestalt(gestaltPsychTable,&tablePtr);            // retrieve the table address
  10.  
  11. SetGestaltValue1.c provides an approximate equivalent for the
  12. SetGestaltValue() function provided in System 7.5 (see Apple's
  13. Gestalt.h), but only requires System 7 or better. SetGestaltValue1()
  14. allows you to install a new Gestalt selector or replace an existing selector
  15. installed by SetGestalt1. DON'T use SetGestaltValue1() to replace a
  16. pre-existing selector NOT installed by SetGestalt1 because its attempt
  17. to free the storage (upp and code) may fail.
  18.  
  19. The Macintosh Gestalt() function provides a way for many autonomous
  20. programs to share a global table. All the programs simply call Gestalt()
  21. with the same selector and Gestalt returns the table address. Any
  22. program calling Gestalt() to get the table address should check that
  23. error==0 and that table!=NULL before using the table. To set the
  24. selector and table address in Gestalt you can either use
  25. SetGestaltValue1 (this file), which works on all Mac Systems and
  26. architectures, or you can use Apple's routines.
  27.  
  28. Instead of using SetGestaltValue1 (this file), you could use Apple's
  29. routines. System 7.5 provides NewGestaltValue() and SetGestaltValue()
  30. (see Apple's Gestalt.h). PowerPC computers require System 7.5 or better,
  31. so your ppc code can safely assume the presence of those routines. If
  32. your program may be run on 68k computers running an earlier System, then
  33. your 68k code should link in Apple's GestaltValue.o library, which Apple
  34. supplies on their developer disks.
  35.  
  36. Invent your own selector name, e.g. gestaltPsychTable. By convention,
  37. the selector name should begin with "gestalt" and end with "Table". Its
  38. value is a four-character code, like 'Psyc'. Apple reserves all the
  39. lowercase-only codes for itself.
  40.  
  41. In order for the Gestalt selector routine to stick around, and not cause
  42. grief to Gestalt by disappearing when the application quits, we follow
  43. Apple's guidelines and install it in the System heap. Once installed
  44. it'll stay there until the machine is rebooted. You can't get rid of a
  45. selector once you've installed it, but you can call SetGestaltValue1()
  46. again, and assign the response NULL.
  47.  
  48. The selector function that we install into the System Heap is 68k code,
  49. because I know how to copy such routines, and have had no success doing
  50. so with ppc code. To have the 68k code available even when this file is
  51. compiled for ppc, without resorting to using resources, i.e. multiple files,
  52. i saved the machine code from a disassembly in a C array.
  53.  
  54. QUESTION:
  55. In thinking about the uses of this routine, it occurred to me that if an
  56. application creates a table in its own heap space and publishes the table's
  57. address via Gestalt, then it might happen that the application is
  58. abnormally terminated before it has a chance to NULL the table address
  59. published by Gestalt. The System would recover the application's memory,
  60. including the table, but the Gestalt value would persist, dangerously
  61. providing a pointer to memory that the System considers unassigned. So,
  62. how can we tell if a table pointer is valid?
  63.  
  64. ANSWER:
  65. Every running application has a unique process serial number (psn). An
  66. application that creates a table in its own heap space and publishes the
  67. table's address via Gestalt should store its psn in the table. Whenever
  68. we retrieve a table address via Gestalt we should check the psn field.
  69. If the table's psn field is not NULL, then we should make sure that that
  70. process is still running. At the moment, David Brainard and I are only
  71. worried about MEX files that all run as part of the MATLAB
  72. application, so it is enough for us to simply make sure that the stored
  73. psn matches our current psn. 
  74.  
  75. #include <Processes.h>
  76. ProcessSerialNumber psn;
  77. Boolean ours;
  78.  
  79. // when we make the table, mark it as our own
  80. error=GetCurrentProcess(&table->psn);
  81.  
  82. // when we access the table, make sure that it's ours
  83. error=GetCurrentProcess(&psn);
  84. error=SameProcess(&table->psn,&psn,&ours);  // Apple says this is the way to compare psns.
  85. if(!ours) table is invalid, 
  86.  
  87. HISTORY:
  88. 5/7/96 dgp wrote it.
  89. 5/9/96 dgp got it to work on ppc.
  90. */
  91.  
  92. #include "VideoToolbox.h"
  93. //#include <Gestalt.h>
  94.  
  95. // modified from Gestalt.h because our routine is ALWAYS 68k code.
  96. #if GENERATINGCFM
  97. #define New68kSelectorFunctionProc(userRoutine)        \
  98.         (SelectorFunctionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), uppSelectorFunctionProcInfo, kM68kISA)
  99. #else
  100. #define New68kSelectorFunctionProc(userRoutine)        \
  101.         ((SelectorFunctionUPP) (userRoutine))
  102. #endif
  103.  
  104. #if (THINK_C || THINK_CPLUS || SYMANTEC_C)
  105.     #pragma options(!profile)
  106. #endif
  107. #if __MWERKS__ && __profile__
  108.     #pragma profile off
  109. #endif
  110.  
  111. // There's nothing special about these numbers. We hope that they won't coincide with
  112. // machine instructions used in the tiny MyGestaltValue program, immediately following.
  113. #define SELECTOR 0x12345678
  114. #define RESPONSE 0x87654321
  115.     
  116. // SetGestaltValue1 copies the compiled version (below) of this code to the
  117. // System heap and sets the copy's selector and response.
  118. pascal OSErr MyGestaltValue(OSType selector,long *response);    // private
  119. pascal OSErr MyGestaltValue(OSType selector,long *response)
  120. {
  121.     if(selector==SELECTOR){
  122.         *response=RESPONSE;
  123.         return 0;
  124.     }else return gestaltUnknownErr;
  125. }
  126.  
  127. /*
  128. MyGestaltValueCode is the 68k compiled code produced by Metrowerks C 8
  129. for the MyGestaltValue routine above. This allows me to install a 68k
  130. code version even when this file is compiled for ppc. I've found it easy
  131. to copy, modify, and install a 68k routine, but haven't succeeded when I
  132. tried to do the same with a ppc routine, because I'm not quite sure what
  133. to do about the indirection through the TVector (nor have I found any
  134. documentation on it.) Apple Developer Tech Support told me that all ppc
  135. routines are called indirectly via a TVector.
  136. */
  137. short myGestaltValueCode[]={
  138.     0x4E56,0x0000            // LINK      A6,#$0000
  139.     ,0x0CAE,0x1234,0x5678    // CMPI.L    #$12345678,$000C(A6)
  140.     ,0x000C           
  141.     ,0x6610                    // BNE.S     *+$0012
  142.     ,0x206E,0x0008            // MOVEA.L   $0008(A6),A0
  143.     ,0x20BC,0x8765,0x4321    // MOVE.L    #$87654321,(A0)
  144.     ,0x426F,0x0010            // CLR.W     $0010(A7)
  145.     ,0x6006                    // BRA.S     *+$0008
  146.     ,0x3F7C,0xEA52,0x0010    // MOVE.W    #$EA52,$0010(A7)
  147.     ,0x4E5E                    // UNLK      A6
  148.     ,0x205F                    // MOVEA.L   (A7)+,A0
  149.     ,0x504F                    // ADDQ.W    #$8,A7
  150.     ,0x4ED0                    // JMP       (A0)
  151.     ,0x8E4D,0x5947,0x4553    // DC.B      $80+$0E, 'MYGESTALTVALUE', $00
  152.     ,0x5441,0x4C54,0x5641 
  153.     ,0x4C55,0x4500,0x0000           
  154. };
  155.  
  156. OSErr SetGestaltValue1(OSType selector,long response)
  157. {
  158.     Ptr ptr;
  159.     OSErr error;
  160.     long value,version;
  161.     SelectorFunctionUPP upp,oldUpp;
  162.     THz heapZone;
  163.     long size;
  164.     unsigned short *wordPtr;
  165.     SelectorFunctionProcPtr functionPtr;
  166.     
  167.     Gestalt(gestaltSystemVersion,&version);
  168.     if(version<0x700)PrintfExit("%s %ld. Sorry. I need System 7 or better.\n",__FILE__,(long)__LINE__);
  169.     functionPtr=(void *)myGestaltValueCode;
  170.     size=sizeof(myGestaltValueCode);
  171.     // copy our function to System Heap
  172.     ptr=NewPtrSys(size);
  173.     if(ptr==NULL)PrintfExit("%s %ld. No space in System Heap.\n",__FILE__,(long)__LINE__);
  174.     BlockMove(functionPtr,ptr,size);
  175.     // Set the copy's selector and response.
  176.     wordPtr=(unsigned short *)ptr;
  177.     wordPtr[3]=selector>>16;
  178.     wordPtr[4]=selector&0xffff;
  179.     wordPtr[10]=response>>16;
  180.     wordPtr[11]=response&0xffff;
  181.     #if GENERATINGPOWERPC
  182.         MakeDataExecutable(ptr,size);
  183.     #else
  184.         FlushCodeCacheRange(ptr,size);
  185.     #endif
  186.     heapZone=GetZone();
  187.     SetZone(SystemZone());
  188.     upp=New68kSelectorFunctionProc(ptr);    // allocate UUP in System Heap
  189.     SetZone(heapZone);
  190.     // does our Gestalt selector already exist?
  191.     error=Gestalt(selector,&value);
  192.     if(!error){
  193.         // yes, replace it. (It may persist from an earlier run of MATLAB.)
  194.         error=ReplaceGestalt(selector,upp,&oldUpp);
  195.         if(error)PrintfExit("%s %ld. ReplaceGestalt error %ld.\n",__FILE__,(long)__LINE__,(long)error);
  196.         // free the old function's space in the System Heap
  197.         if(oldUpp!=NULL){
  198.             #if GENERATINGCFM
  199.                 DisposePtr((Ptr)oldUpp->routineRecords[0].procDescriptor);
  200.             #endif
  201.             DisposePtr((Ptr)oldUpp);
  202.         }
  203.     }else{
  204.         // no, install it.
  205.         error=NewGestalt(selector,upp);
  206.         if(error)PrintfExit("%s %ld. NewGestalt error %ld.\n",__FILE__,(long)__LINE__,(long)error);
  207.     }
  208.     return error;
  209. }
  210.